package com.ruoyi.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.*;
import com.ruoyi.common.cont.SysConst;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.common.utils.secret.AESUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.domain.SysUserPost;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.domain.dto.StudentDto;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.validation.Validator;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户 业务层处理
 *
 * @author ruoyi
 */
@Service
public class SysUserServiceImpl implements ISysUserService
{
    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysPostMapper postMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysUserPostMapper userPostMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    protected Validator validator;
    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Override
    public SysUser getDefaultUser() {
        return userMapper.getDefaultUser();
    }

    @Override
    public SysUser getPoByDo(SysUser conditionDo)
    {
        return userMapper.getPoByDo(conditionDo);
    }

    /**
     * 根据条件分页查询机构用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserList(SysUser user)
    {
        if (!SysUser.isAdminTypeCode(SecurityUtils.getTypeCode())) {
            user.setParentId(SecurityUtils.getUserId());
        }
        List<SysUser> sysUsers = userMapper.selectUserList(user);
        return sysUsers;
    }

    /**
     * 根据条件分页查询机构用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectInsUserList(SysUser user)
    {
        List<SysUser> sysUsers = userMapper.selectUserList(user);
        for (SysUser sysUser : sysUsers) {
            if (SysUserCodeConstants.UserCode.ASSOCIATION.getCode().equals(sysUser.getTypeCode())
                    || SysUserCodeConstants.UserCode.INSTITUTION.getCode().equals(sysUser.getTypeCode())) {
                //完善补充机构用户信息
                applyInsUserInfo(sysUser);
            }
        }
        return sysUsers;
    }

    /**
     * 根据条件分页查询企业用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    public List<SysUser> selectEntUserList(SysUser user)
    {
        applyCondition(user);
        List<SysUser> sysUsers = userMapper.selectEntUserList(user);
        for (SysUser sysUser : sysUsers) {
            if (SysUserCodeConstants.UserCode.ENTERPRISE.getCode().equals(sysUser.getTypeCode())) {
                //完善补充企业用户信息
                applyEntUserInfo(sysUser);
            }
        }
        return sysUsers;
    }

    /**
     * 补充查询条件
     *
     * @param user 传参
     */
    private void applyCondition(SysUser user)
    {
        if (!SysUser.isAdminTypeCode(SecurityUtils.getTypeCode())) {
            //如果不是管理员，那么只看自己机构下的企业
            user.setParentId(SecurityUtils.getUserId());
        }
    }

    /**
     * 完善补充企业用户信息
     *
     * @param sysUser 当前企业
     */
    private void applyEntUserInfo(SysUser sysUser)
    {
        //归属机构
        if (ObjectUtil.isEmpty(sysUser.getParentName())) {
            sysUser.setParentName("/");
        }
        //学生数量
        if (ObjectUtil.isEmpty(sysUser.getStudentNum())) {
            sysUser.setStudentNum(0L);
        }
    }

    /**
     * 完善补充机构用户信息
     *
     * @param sysUser 当前机构
     */
    private void applyInsUserInfo(SysUser sysUser)
    {
        //查询下级企业
        SysUser condition = new SysUser();
        condition.setParentId(sysUser.getUserId());
        Long aLong = userMapper.selectCount(condition);
        sysUser.setEntNum(aLong);
    }

    /**
     * 根据条件分页查询已分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectAllocatedList(SysUser user)
    {
        return userMapper.selectAllocatedList(user);
    }

    /**
     * 根据条件分页查询未分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUnallocatedList(SysUser user)
    {
        return userMapper.selectUnallocatedList(user);
    }

    /**
     * 通过用户名查询用户
     *
     * @param userName 用户名
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserByUserName(String userName)
    {
        return userMapper.selectUserByUserName(userName);
    }

    /**
     * 通过用户ID查询用户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public SysUser selectUserById(Long userId)
    {
        SysUser sysUser = userMapper.selectUserById(userId);
        sysUser.setPassword(null);
        return sysUser;
    }

    /**
     * 查询用户所属角色组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserRoleGroup(String userName)
    {
        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
        if (CollectionUtils.isEmpty(list)) {
            return StringUtils.EMPTY;
        }
        return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
    }

    /**
     * 查询用户所属岗位组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserPostGroup(String userName)
    {
        List<SysPost> list = postMapper.selectPostsByUserName(userName);
        if (CollectionUtils.isEmpty(list)) {
            return StringUtils.EMPTY;
        }
        return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean checkUserNameUnique(SysUser user)
    {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkUserNameUnique(user.getUserName());
        //如果名称相同且主键不等，判断为已存在相同姓名
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验手机号码是否唯一
     *
     * @param user 用户信息
     * @return
     */
    @Override
    public boolean checkPhoneUnique(SysUser user)
    {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验机构代码是否唯一
     *
     * @param user 用户信息
     * @return 结果 true唯一false不唯一
     */
    @Override
    public boolean checkOrganCodeUnique(SysUser user)
    {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkOrganCodeUnique(user.getOrganCode());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验统一信用代码是否唯一
     *
     * @param user 用户信息
     * @return true唯一 false不唯一
     */
    @Override
    public boolean checkSocialCode(SysUser user)
    {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkSocialCode(user.getSocialCode());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验在当前机构下，企业的统一信用代码是否唯一
     *
     * @param user     用户信息
     * @param typeCode save新增操作 update修改操作
     * @return true唯一 false不唯一
     */
    public boolean checkEntSocialCode(SysUser user, String typeCode)
    {
        SysUser sysUser = new SysUser();
        //1.所属机构id
        //如果是管理员操作，父级就是默认机构；否则就是当前登陆人
        if (SysUser.isAdmin(SecurityUtils.getUserId())) {
            SysUser condition = new SysUser();
            condition.setDefaultFlag(1);
            List<SysUser> sysUsers = userMapper.selectUserByCondition(condition);
            if (sysUsers != null && sysUsers.size() > 0) {
                SysUser parentUser = sysUsers.get(0);
                sysUser.setParentId(parentUser != null ? parentUser.getUserId() : null);
            }
        } else {
            sysUser.setParentId(SecurityUtils.getUserId());
        }
        //2.社会统一信用代码
        sysUser.setSocialCode(user.getSocialCode());
        //查询改机构下同样社会信用代码的用户
        List<SysUser> sysUsers = userMapper.selectUserByCondition(sysUser);
        boolean result = false;
        if (sysUsers.size() == 0) {
            result = true;
        } else if (SysConst.OPERATE.UPDATE.getCode().equals(typeCode) && (user.getUserId().equals(sysUsers.get(0).getUserId()))) {
            result = true;
        }
        return result;
    }

    /**
     * 校验email是否唯一
     *
     * @param user 用户信息
     * @return
     */
    @Override
    public boolean checkEmailUnique(SysUser user)
    {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkEmailUnique(user.getEmail());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    @Override
    public void checkUserAllowed(SysUser user)
    {
        if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) {
            throw new ServiceException("不允许操作超级管理员用户");
        }
    }

    /**
     * 校验用户是否有数据权限
     *
     * @param userId 用户id
     */
    @Override
    public void checkUserDataScope(Long userId)
    {
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            SysUser user = new SysUser();
            user.setUserId(userId);
            List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
            if (StringUtils.isEmpty(users)) {
                throw new ServiceException("没有权限访问用户数据！");
            }
        }
    }

    /**
     * 新增保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUser(SysUser user)
    {
        //检查当前是否被设置为默认企业
        checkDefaultFlag(user);
        //没有选择部门就赋予默认部门
        setDefaultDeptIfNoChoose(user);
        // 新增用户信息
        int rows = userMapper.insertUser(user);
        // 新增用户岗位关联 岗位默认：普通员工
        insertUserPost(user);
        // 新增用户与角色管理
        insertUserRole(user);
        return rows;
    }

    private void setDefaultDeptIfNoChoose(SysUser user)
    {
        Long deptId = user.getDeptId();
        if (ObjectUtil.isNull(deptId)) {
            SysDept deptCondition = new SysDept();
            deptCondition.setDeptCode(DeptCodeConstants.DeptCode.ISDEFAULT.getCode());
            SysDept sysDept = sysDeptMapper.selectDeptByCondition(deptCondition);
            if (sysDept != null) {
                user.setDeptId(sysDept.getDeptId());
            }
        }
    }

    /**
     * 检查是否被设置为默认企业
     *
     * @param user 新增的企业
     */
    private void checkDefaultFlag(SysUser user)
    {
        if (ObjectUtil.isNotNull(user.getDefaultFlag())
                && user.getDefaultFlag().equals(1)) {
            userMapper.cancelDefault();
        } else {
            user.setDefaultFlag(0);
        }
    }

    /**
     * 注册用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean registerUser(SysUser user)
    {
        return userMapper.insertUser(user) > 0;
    }

    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateUser(SysUser user)
    {
        Long userId = user.getUserId();
        // 删除用户与角色关联
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 新增用户与角色管理
        insertUserRole(user);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPostByUserId(userId);
        // 新增用户与岗位管理
        insertUserPost(user);
        // 判断是否改为默认
        if (1 == user.getDefaultFlag()) {
            userMapper.cancelDefault();
        }
        return userMapper.updateUser(user);
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertUserAuth(Long userId, Long[] roleIds)
    {
        userRoleMapper.deleteUserRoleByUserId(userId);
        insertUserRole(userId, roleIds);
    }

    /**
     * 修改用户状态
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserStatus(SysUser user)
    {
        return userMapper.updateUser(user);
    }

    /**
     * 修改用户基本信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserProfile(SysUser user)
    {
        return userMapper.updateUser(user);
    }

    /**
     * 修改用户头像
     *
     * @param userName 用户名
     * @param avatar   头像地址
     * @return 结果
     */
    @Override
    public boolean updateUserAvatar(String userName, String avatar)
    {
        return userMapper.updateUserAvatar(userName, avatar) > 0;
    }

    /**
     * 重置用户密码
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int resetPwd(SysUser user)
    {
        return userMapper.updateUser(user);
    }

    /**
     * 重置用户密码
     *
     * @param userName 用户名
     * @param password 密码
     * @return 结果
     */
    @Override
    public int resetUserPwd(String userName, String password)
    {
        return userMapper.resetUserPwd(userName, password);
    }

    /**
     * 新增用户角色信息
     *
     * @param user 用户对象
     */
    public void insertUserRole(SysUser user)
    {
        this.insertUserRole(user.getUserId(), user.getRoleIds());
    }

    /**
     * 新增用户岗位信息
     *
     * @param user 用户对象
     */
    public void insertUserPost(SysUser user)
    {
        //岗位默认给 普通员工
        SysPost condition = new SysPost();
        condition.setPostCode(UserPostConstants.UserPostCode.USER.getCode());
        SysPost sysPost = postMapper.getBodyByCondition(condition);
        Long[] posts = Collections.singletonList(sysPost.getPostId()).toArray(new Long[0]);

        if (StringUtils.isNotEmpty(posts)) {
            // 新增用户与岗位管理
            List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
            for (Long postId : posts) {
                SysUserPost up = new SysUserPost();
                up.setUserId(user.getUserId());
                up.setPostId(postId);
                list.add(up);
            }
            userPostMapper.batchUserPost(list);
        }
    }

    /**
     * 新增用户角色信息
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    public void insertUserRole(Long userId, Long[] roleIds)
    {
        if (StringUtils.isNotEmpty(roleIds)) {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
            for (Long roleId : roleIds) {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(userId);
                ur.setRoleId(roleId);
                list.add(ur);
            }
            userRoleMapper.batchUserRole(list);
        }
    }

    /**
     * 通过用户ID删除用户
     *
     * @param userId 用户ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteUserById(Long userId)
    {
        // 删除用户与角色关联
        userRoleMapper.deleteUserRoleByUserId(userId);
        // 删除用户与岗位表
        userPostMapper.deleteUserPostByUserId(userId);
        return userMapper.deleteUserById(userId);
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteUserByIds(Long[] userIds)
    {
        for (Long userId : userIds) {
            checkUserAllowed(new SysUser().setUserId(userId));
            checkUserDataScope(userId);
        }
        // 删除用户与角色关联
        userRoleMapper.deleteUserRole(userIds);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPost(userIds);
        return userMapper.deleteUserByIds(userIds);
    }

    /**
     * 导入用户数据
     *
     * @param userList        用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param createBy        操作用户
     * @return 结果
     */
    @Override
    public String importUser(List<SysUser> userList, Boolean isUpdateSupport, Long createBy)
    {
        if (StringUtils.isNull(userList) || userList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        String password = configService.selectConfigByKey("sys.user.initPassword");
        for (SysUser user : userList) {
            try {
                // 验证是否存在这个用户
                SysUser u = userMapper.selectUserByUserName(user.getUserName());
                if (StringUtils.isNull(u)) {
                    BeanValidators.validateWithException(validator, user);
                    user.setPassword(SecurityUtils.encryptPassword(password));
                    user.setCreateBy(createBy);
                    userMapper.insertUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, user);
                    checkUserAllowed(u);
                    checkUserDataScope(u.getUserId());
                    user.setUserId(u.getUserId());
                    user.setUpdateBy(createBy);
                    userMapper.updateUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public String checkUserInfo(SysUser user)
    {
        if (StringUtils.isNotEmpty(user.getPassword()) &&
                (StringUtils.isNotEmpty(user.getRePassword()) && !user.getPassword().equals(user.getRePassword()))) {
            return ("操作用户'" + user.getNickName() + "'失败，两次密码不一致");
        } else if (!checkUserNameUnique(user)) {
            return ("操作用户'" + user.getNickName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getOrganCode()) && !checkOrganCodeUnique(user)) {
            return ("操作用户'" + user.getNickName() + "'失败，机构代码已存在");
        } else if (StringUtils.isNotEmpty(user.getSocialCode()) && !checkSocialCode(user)) {
            return ("操作用户'" + user.getNickName() + "'失败，统一信用代码已存在");
        }
        return null;
    }

    /**
     * 检查传参数据是否正确（企业用户）
     *
     * @param user
     * @param typeCode save新增操作 update修改操作
     * @return
     */
    @Override
    public String checkEntUserInfo(SysUser user, String typeCode)
    {
        if (StringUtils.isEmpty(user.getNickName())) {
            return ("新增用户失败，企业名称未填写");
        } else if (StringUtils.isEmpty(user.getSocialCode()) || !checkEntSocialCode(user, typeCode)) {
            return ("新增用户'" + user.getNickName() + "'失败，统一信用代码未填写或已存在！");
        }
        return null;
    }

    /**
     * 用户的启用停用
     *
     * @param user
     * @return
     */
    @Override
    public boolean enableUser(SysUser user)
    {
        if (ObjectUtil.isEmpty(user.getUserId())) {
            throw new GlobalException("用户id不能为空");
        }
        int i = userMapper.updateUser(user);
        return i > 0;
    }

    /**
     * 重置密码
     *
     * @param user
     * @return
     */
    @Override
    public boolean rePassword(SysUser user)
    {
        if (ObjectUtil.isEmpty(user.getUserId())) {
            throw new GlobalException("用户id不能为空！");
        }
        SysUser sysUser = userMapper.selectUserById(user.getUserId());
        if (sysUser == null) {
            throw new GlobalException("没有该用户！");
        }
        String userName = sysUser.getUserName();
        if (!SysUser.isAdminTypeCode(SecurityUtils.getTypeCode()) && sysUser.getParentId().equals(SecurityUtils.getUserId())) {
            throw new GlobalException("该机构/企业非当前用户下级，无权限修改");
        }
        int num = SysUserCodeConstants.UserCode.ENTERPRISE.getCode().equals(user.getTypeCode()) ? 5 : 6;
        if (userName.length() < num) {
            throw new GlobalException("账户长度小于重置位数");
        }
        String substring = userName.substring(userName.length() - num);
        //加密
        sysUser.setPassword(SecurityUtils.encryptPassword(substring));
        sysUser.setPasswordView(AESUtil.encrypt(substring));
        return userMapper.updateUser(sysUser) > 0;
    }

    /**
     * 机构生成企业时，生成企业账号信息
     *
     * @param userId 机构id
     * @param user   企业信息
     */

    @Override
    public SysUser createEntUserInfo(Long userId, SysUser user)
    {
        //关联机构
        SysUser parentUser = null;
        if (SysUser.isAdmin(userId) || ObjectUtil.isEmpty(userId)) {
            SysUser condition = new SysUser();
            condition.setDefaultFlag(1);
            List<SysUser> sysUsers = userMapper.selectUserByCondition(condition);
            if (sysUsers != null && sysUsers.size() > 0) {
                parentUser = sysUsers.get(0);
                user.setParentId(parentUser != null ? parentUser.getUserId() : null);
            }
        } else {
            parentUser = userMapper.selectUserById(userId);
            user.setParentId(userId);
        }
        if (parentUser == null) {
            throw new GlobalException("未找到当前用户或未配置默认机构！");
        }
        //创建账户密码
        // 账号规则为 所属机构代码 + 5位不重复随机编码(大写字符和数字共36个字符，保证唯一)
        // 密码生成规则 随机5位(大写字符和数字共36个字符，随机)
        String userName = parentUser.getOrganCode() + StringUtils.getRandomString(5);
        String password = StringUtils.getRandomString(5);
        user.setUserName(userName);
        user.setPassword(SecurityUtils.encryptPassword(password));
        user.setPasswordView(AESUtil.encrypt(password));
        user.setRePassword(password);
        user.setTypeCode(SysUserCodeConstants.UserCode.ENTERPRISE.getCode());
        user.setDefaultFlag(0);
        SysRole condition = new SysRole();
        condition.setRoleKey(UserRoleConstants.UserRoleCode.ENTERPRISE.getCode());
        SysRole sysRole = roleMapper.selectRoleByCondition(condition);
        Long roleId = sysRole != null ? sysRole.getRoleId() : null;
        user.setRoleIds(new Long[]{roleId});
        return user;
    }

    /**
     * 校验数据是否重复
     * true唯一 false不唯一
     *
     * @param user
     */
    @Override
    public boolean verifyRepeatData(SysUser user)
    {
        String verifyType = user.getVerifyType();
        if (StringUtils.isEmpty(verifyType)) {
            throw new GlobalException("请选择校验类型！");
        }
        boolean verifyFlag = true;
        switch (verifyType) {
            case "1":
                verifyFlag = checkSocialCode(user);
                break;
            case "2":
                verifyFlag = checkOrganCodeUnique(user);
                break;
            case "3":
                verifyFlag = checkUserNameUnique(user);
                break;
            default:
        }
        return verifyFlag;
    }

    /**
     * 判断是否有权限修改该企业用户
     *
     * @param user     企业用户
     * @param typeCode 修改人
     * @param userId   修改人用户
     */
    @Override
    public void checkEditEntUserAuth(SysUser user, String typeCode, Long userId)
    {
        if (!SysUser.isAdminTypeCode(typeCode)) {
            if (user.getParentId() != null && !user.getParentId().equals(userId)) {
                throw new GlobalException("无权限修改该企业用户！");
            }
        }
    }

    /**
     * 统计企业下的学员数量
     * 只统计 已通过状态status=2的学员
     *
     * @param userId 企业id
     * @return
     */
    @Override
    public int countStudent(Long userId)
    {
        //统计企业下的学员数量,只统计 已通过状态status=2的学员
        return userMapper.countStudentByCondition(new StudentDto().setEntId(userId).setStatus("2"));
    }

    /**
     * 维护机构用户信息
     *
     * @param user
     * @return
     */
    @Override
    public SysUser createInsUserInfo(SysUser user)
    {
        //设置默认角色为机构
        SysRole condition = new SysRole();
        condition.setRoleKey(UserRoleConstants.UserRoleCode.INSTITUTION.getCode());
        SysRole sysRole = roleMapper.selectRoleByCondition(condition);
        Long roleId = sysRole != null ? sysRole.getRoleId() : null;
        user.setRoleIds(new Long[]{roleId});
        user.setParentId(SecurityUtils.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setPasswordView(AESUtil.encrypt(user.getPassword()));
        return user;
    }

    /**
     * 维护管理员用户信息
     *
     * @param user 用户数据
     * @return
     */
    @Override
    public SysUser createManagerUserInfo(SysUser user)
    {
        user.setRoleIds(user.getRoleIds());
        user.setParentId(SecurityUtils.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setPasswordView(AESUtil.encrypt(user.getPassword()));
        return user;
    }


    /**
     * 获取机构-企业树列表
     *
     * @param sysUser
     * @return
     */
    @Override
    public List<SysUser> selectUserTreeList(SysUser sysUser)
    {
        //不是管理员，只看自己下面的企业
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            sysUser.setParentId(SecurityUtils.getUserId());
        }
        //查全部满足检索条件的单位
        List<SysUser> sysUsers = querySysUserByCondition(sysUser);
        if (sysUsers == null || sysUsers.size() == 0) {
            return sysUsers;
        }
        //学员数量、缴费金额查询
        queryUserConInfo(sysUser.getStartDate(), sysUser.getEndDate(), sysUsers);
        //构建树形
        return createSysUserTree(sysUsers);
    }


    private List<SysUser> querySysUserByCondition(SysUser sysUser)
    {
        Long currentId = SecurityUtils.getUserId();
        if (StringUtils.isNotBlank(sysUser.getNickName()) && StringUtils.isNotBlank(sysUser.getParentName())) {
            //查具体机构下的企业
            List<SysUser> sysUsers = userMapper.selectUserTreeList(sysUser);
            //还需要再关联一下机构
            sysUsers = applyInfoList(sysUsers, SysUserCodeConstants.UserCode.INSTITUTION.getCode());
            return sysUsers;
        } else if (StringUtils.isBlank(sysUser.getNickName()) && StringUtils.isNotBlank(sysUser.getParentName())) {
            //查机构
            List<String> codeList = Lists.newArrayList();
            codeList.add(SysUserCodeConstants.UserCode.ASSOCIATION.getCode());
            codeList.add(SysUserCodeConstants.UserCode.INSTITUTION.getCode());
            List<SysUser> sysUsers = userMapper.selectUserByCondition(new SysUser()
                    .setNickName(sysUser.getParentName())
                    .setUserId(SysUser.isAdmin(currentId) ? null : currentId)
                    .setTypeCodeList(codeList));
            if (sysUsers.size() == 0) {
                return null;
            }
            //关联一下企业
            sysUsers = applyInfoList(sysUsers, SysUserCodeConstants.UserCode.ENTERPRISE.getCode());
            return sysUsers;
        } else if (StringUtils.isBlank(sysUser.getParentName()) && StringUtils.isNotBlank(sysUser.getNickName())) {
            //查企业
            List<SysUser> sysUsers = userMapper.selectUserByCondition(new SysUser()
                    .setNickName(sysUser.getNickName())
                    .setParentId(SysUser.isAdmin(currentId) ? null : sysUser.getParentId())
                    .setTypeCode(SysUserCodeConstants.UserCode.ENTERPRISE.getCode()));
            if (sysUsers.size() == 0) {
                return null;
            }
            //还需要再关联一下机构
            sysUsers = applyInfoList(sysUsers, SysUserCodeConstants.UserCode.INSTITUTION.getCode());
            return sysUsers;
        } else {
            //查询自己机构下的
            return userMapper.selectUserTreeList(sysUser);
        }
    }


    /**
     * 查看密码明文
     *
     * @param user 入参
     * @return
     */
    @Override
    public String viewPassword(SysUser user)
    {
        SysUser sysUser = userMapper.selectUserById(user.getUserId());
        if (sysUser == null) {
            throw new GlobalException("未找到该用户！");
        }
        String passwordView = sysUser.getPasswordView();
        String password = AESUtil.decrypt(passwordView);
        if (StrUtil.isBlank(password)) {
            throw new GlobalException("解密出错，检查密码是否存在！");
        }
        return password;
    }

    /**
     * 校验参数是否为空
     *
     * @param user 传参
     */
    @Override
    public void checkParam(SysUser user)
    {
        if (user.getRoleIds() == null || user.getPostIds() == null
                || user.getDefaultFlag() == null) {
            throw new GlobalException("参数错误");
        }
    }

    /**
     * 创建树形结构
     *
     * @param sysUsers 用户信息列表
     */
    private List<SysUser> createSysUserTree(List<SysUser> sysUsers)
    {
        Map<Long, List<SysUser>> userListGroupByParentId
                = sysUsers.stream().collect(Collectors.groupingBy(SysUser::getParentId));
        for (SysUser sysUser : sysUsers) {
            if (userListGroupByParentId.containsKey(sysUser.getUserId())) {
                sysUser.setChildren(userListGroupByParentId.get(sysUser.getUserId()));
            }
        }
        //剔除掉企业的
        return sysUsers
                .stream()
                .filter(o -> !SysUserCodeConstants.UserCode.ENTERPRISE.getCode().equals(o.getTypeCode()) && !SysUser.isAdminTypeCode(o.getTypeCode()))
                .collect(Collectors.toList());
    }

    /**
     * 查询用户的关联信息（包括学生数量、缴费金额）
     * **如果是管理员来创建学员，那就创建人为默认机构
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param sysUsers  集合
     */
    private List<SysUser> queryUserConInfo(Date startDate, Date endDate, List<SysUser> sysUsers)
    {
        for (SysUser sysUser : sysUsers) {
            //过滤出机构,机构学员使用ins_id来关联
            if (!SysUserCodeConstants.UserCode.ENTERPRISE.getCode().equals(sysUser.getTypeCode()) && !SysUser.isAdmin(sysUser.getUserId())) {
                //不过滤 是否过期；针对学员到期日期进行过滤,查询学员数量
                StudentDto studentDto = new StudentDto()
                        .setInsId(sysUser.getUserId())
                        .setStartDate(startDate)
                        .setEndDate(endDate);
                int num = userMapper.countStudentByCondition(studentDto);
                sysUser.setStudentNum((long) num);
                //查询机构导入的批次的缴费金额总额
                BigDecimal sumPrice = userMapper.queryBatchPriceSum(sysUser.getUserId());
                sysUser.setPayPriceSum(sumPrice);
            }
            //企业,学员使用ent_id来关联
            if (SysUserCodeConstants.UserCode.ENTERPRISE.getCode().equals(sysUser.getTypeCode())) {
                //不过滤 是否过期；针对学员到期日期进行过滤,查询学员数量
                StudentDto studentDto = new StudentDto()
                        .setEntId(sysUser.getUserId())
                        .setStartDate(startDate)
                        .setEndDate(endDate);
                int num = userMapper.countStudentByCondition(studentDto);
                sysUser.setStudentNum((long) num);
                //查询指定给该企业的学员的单价总和
                BigDecimal sumPrice = userMapper.queryStudentUnitPriceSum(sysUser.getUserId());
                sysUser.setPayPriceSum(sumPrice);
            }
        }
        return sysUsers;
    }

    /**
     * 关联一下机构列表
     *
     * @param sysUsers 数据库查询的结构list
     */
    private List<SysUser> applyInsList(List<SysUser> sysUsers)
    {
        List<Long> userIdList = sysUsers.stream().map(SysUser::getParentId).collect(Collectors.toList());
        List<SysUser> parentSysUser = userMapper.selectUserByCondition(new SysUser().setUserIdList(userIdList));
        sysUsers.addAll(parentSysUser);
        //去重
        ArrayList<SysUser> ageDistinctList = sysUsers
                .stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SysUser::getUserId)))
                        ,
                        ArrayList::new
                ));
        return ageDistinctList;
    }

    /**
     * 关联一下信息
     *
     * @param sysUsers 数据库查询的结构list
     * @param code     关联机构 institution 关联企业 enterprise
     * @return
     */
    private List<SysUser> applyInfoList(List<SysUser> sysUsers, String code)
    {
        if (SysUserCodeConstants.UserCode.INSTITUTION.getCode().equals(code)) {
            List<Long> userIdList = sysUsers.stream().map(SysUser::getParentId).collect(Collectors.toList());
            List<SysUser> parentSysUser = userMapper.selectUserByCondition(new SysUser().setUserIdList(userIdList));
            sysUsers.addAll(parentSysUser);
        } else if (SysUserCodeConstants.UserCode.ENTERPRISE.getCode().equals(code)) {
            List<Long> userIdList = sysUsers.stream().map(SysUser::getUserId).collect(Collectors.toList());
            List<SysUser> childrenSysUser = userMapper.selectUserByCondition(new SysUser().setParentIdList(userIdList));
            sysUsers.addAll(childrenSysUser);
        }
        //去重
        ArrayList<SysUser> ageDistinctList = sysUsers
                .stream()
                .collect(Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SysUser::getUserId)))
                        ,
                        ArrayList::new
                ));
        return ageDistinctList;
    }
}
